本篇將來介紹 Enum
,你會了解到什麼是 「Numeric Enums」, 「String Enums」,「計算成員」以及 Enum 中「反向查找」和「雙向映射」的特性
🚪 文章傳送門 🚪
Enum 是「Enumerated」的縮寫,中文翻為「列舉」、「枚舉」,是 TypeScript 獨有的型別
語法:
enum <enum's name> { ... }
enum
關鍵字來定義enum's name
和裡面的項目一般是「大寫開頭」,使用 PascalCase 命名法,例如:enum Days { Sun, Mon ... }
TypeScript 提供基於數字和字串的列舉
Enum 的列舉項被初始化時,會從 0
開始按順序持續遞增 1, 2, ...
enum Direction {
Up,
Down,
Left,
Right,
};
console.log(Direction.Up); // 0
console.log(Direction.Down); // 1
console.log(Direction.Left); // 2
console.log(Direction.Right); // 3
也可以手動賦值,記得是用 =
,有時候我會冒號、等於搞混XD
未手動賦值的列舉項,會承接著上一個列舉項的值繼續遞增
enum Direction {
Up = 1,
Down = 3,
Left,
Right,
};
console.log(Direction.Up); // 1
console.log(Direction.Down); // 3
console.log(Direction.Left); // 4
console.log(Direction.Right); // 5
手動賦值後,假設在遞增個過程時,又出現重複的值,TypeScript 是「不會」報錯的,這點要特別留意~
enum Direction {
Up = 2,
Down = 1,
Left,
Right,
};
console.log(Direction.Up); // 2
console.log(Direction.Down); // 1
console.log(Direction.Left); // 2 重複了!
console.log(Direction.Right); // 3
string literal 字串字面量
來初始化Enum member must have initializer.
enum StrDirection {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT", // 把值拿掉會報錯 Enum member must have initializer.
}
「數字」和「字串」也是可以混合在同個 enum 裡喔~又稱為異構列舉(Heterogeneous enums)
雖然這樣做不會報錯,但官方並不建議,因為在語意和意義上沒什麼幫助,反而還可能讓程式變得更難理解與維護
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
接著,不論是「字串列舉」還是「數字列舉」都是屬於 constant enum expression 常數列舉表達式
,可以使用 +, -, *, /, %, <<, >>, >>>, &, |, ^
等二元運算子來計算常數
「constant enum expression 常數列舉表達式」會在編譯時
就被計算出,不用到 runtime(相反的 computed 屬性就會在 runtime 時計算)
以下範例僅供示意
enum Set {
// constant members
A,
B = 5,
C = 1 + 2,
D = 1 - 3,
E = 2 * 2
}
範例中,A
和 B
都是屬於計算成員(在 runtime 時被計算)
,而 C
沒有明確的賦值(初始化),就會報錯
💡 如果列舉中有成員沒有初始化,它的位置要馬是在第一個,要馬就是在使用數字初始化的枚舉項之後
enum computedEnum {
A = getSomeValue(), // computed member
B = "123".length, // computed member
C, // ❌ Enum member must have initializer.
}
// 改成這樣就不會報錯了,範例僅供示意
enum E2 {
C, // 0
A = getSomeValue(),
B = "123".length,
}
綜合以上來看
computed (計算)的列舉成員會在 runtime 時才被計算,因此無法在 compile 時就確定
constant (常數)的列舉成員在 compile 時就被計算
反向查找就是指「我可以透過 value 來反查 key」,這個特性只有在 「數字列舉」才有
由下例可得知,我們能透過 value 來查找 key, 也可以透過 key 來查找 value,這稱為「雙向映射
」
也只有「數字列舉
」才會產生「雙向映射
」,「字串列舉
」則是「單向映射
」
enum ReverseMapping {
A,
};
console.log(ReverseMapping.A) // 0
console.log(ReverseMapping[0]) // A
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
console.log(Direction.Up); // UP
console.log(Direction["UP"]); // undefined
enum TaskStatus {
Pending,
InProgress,
Completed,
};
let tasks: {title: string, status: TaskStatus}[] = []; // 格式為陣列包物件
function title (title: string) {
tasks.push({
title,
status: TaskStatus.Completed,
});
};
title('寫鐵人賽');
console.log('tasks', tasks); // [ { title: '寫鐵人賽', status: 2 } ]
項目 | 數字列舉 | 字串列舉 |
---|---|---|
初始化 | 每個成員初始化為數字,未初始化則自動從 0 開始遞增 | 每個成員初始化為字串字面量 |
雙向映射 | 有 | 無,為單向映射 |
可讀性 | 較低 | 較高 |
範例 | enum Status { Active } |
enum Status { Active = "ACTIVE" } |
每天講的內容有推到 github 上喔